﻿/* Author:
 *  Andrea Vandin
 */
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TripLOAMobile
{
    /// <summary>
    /// This control makes an animation used during the remote requests
    /// </summary>
    public partial class AnimationControl : Control
    {
        public static bool USESTANDARDAPPLICATIONANIMATION;

        private List<Bitmap> frames;
        private int actualPosition=0;
        private Timer fTimer;
        private Bitmap _actualAnimation;

        private bool usingStandardApplicationAnimation;

        Brush brushBackGround;

        private bool isAnimating = false;

        /// <summary>
        /// Gets or sets the actual animation theme.
        /// </summary>
        /// <value>The actual animation.</value>
        private Bitmap actualAnimation
        {
            get
            {
                return _actualAnimation;
            }
            set
            {
                _actualAnimation = value;
                this.Invalidate();
                this.Update();
            }
        }

        /// <summary>
        /// Initializes the <see cref="AnimationControl"/> class.
        /// </summary>
        static AnimationControl()
        {
            USESTANDARDAPPLICATIONANIMATION = true;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AnimationControl"/> class.
        /// </summary>
        /// <param name="intervalInMillisecond">The interval in millisecond.</param>
        public AnimationControl(int intervalInMillisecond)
        {
            this.CommonConstructorCode(intervalInMillisecond);
            this.loadAndSetApplicationDefaultAnimation();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AnimationControl"/> class, using a default interval.
        /// </summary>
        public AnimationControl():this(250)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AnimationControl"/> class.
        /// </summary>
        /// <param name="intervalInMillisecond">The interval in millisecond.</param>
        /// <param name="listOfFrames">The list of frames.</param>
        public AnimationControl(int intervalInMillisecond, params Bitmap[] listOfFrames)
        {
            this.CommonConstructorCode(intervalInMillisecond);
            this.setFramesAnimation(listOfFrames);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AnimationControl"/> class.
        /// </summary>
        /// <param name="listOfFrames">The list of frames.</param>
        public AnimationControl(params Bitmap[] listOfFrames)
            : this(250, listOfFrames)
        {
        }

        /// <summary>
        /// Commons the constructor code.
        /// </summary>
        /// <param name="intervalInMillisecond">The interval in millisecond.</param>
        private void CommonConstructorCode(int intervalInMillisecond)
        {
            InitializeComponent();
            this.BackColor = Color.FromArgb(0, 0, 0);
            brushBackGround = new SolidBrush(this.BackColor);
            fTimer = new System.Windows.Forms.Timer();
            fTimer.Tick += new System.EventHandler(this.timer_Tick);
            fTimer.Interval = intervalInMillisecond;
            this.Enabled = false;
            this.Visible = false;
            fTimer.Enabled = false;
        }

        /// <summary>
        /// Sets the frames animation.
        /// </summary>
        /// <param name="listOfFrames">The list of frames.</param>
        public void setFramesAnimation(Bitmap[] listOfFrames){
            frames = new List<Bitmap>(listOfFrames);
            this.Size= new Size(listOfFrames[0].Width, listOfFrames[0].Height);
            this.actualAnimation = listOfFrames[0];
        }

        /// <summary>
        /// Loads the and set mobile default animation theme.
        /// </summary>
        private void loadAndSetMobileDefaultAnimation(){
            this.usingStandardApplicationAnimation = false;
            if (frames != null)
            {
                foreach (Bitmap b in frames)
                    b.Dispose();
                frames.Clear();
            }

            frames.Add(TripLOAMobile.Properties.Resources.Win_1);
            frames.Add(TripLOAMobile.Properties.Resources.Win_2);
            frames.Add(TripLOAMobile.Properties.Resources.Win_3);
            frames.Add(TripLOAMobile.Properties.Resources.Win_4);
            frames.Add(TripLOAMobile.Properties.Resources.Win_5);
            frames.Add(TripLOAMobile.Properties.Resources.Win_6);
            frames.Add(TripLOAMobile.Properties.Resources.Win_7);
            frames.Add(TripLOAMobile.Properties.Resources.Win_8);
            frames.Add(TripLOAMobile.Properties.Resources.Win_9);
            frames.Add(TripLOAMobile.Properties.Resources.Win_10);
            frames.Add(TripLOAMobile.Properties.Resources.Win_11);

            this.Size = new Size(frames[0].Width, frames[0].Height);
            this.actualAnimation = frames[0];
        }

        /// <summary>
        /// Loads the and set application default animation theme.
        /// </summary>
        private void loadAndSetApplicationDefaultAnimation()
        {
            this.usingStandardApplicationAnimation = true;
            if (frames != null)
            {
                foreach (Bitmap b in frames)
                    b.Dispose();
                frames.Clear();
            }

            frames = new List<Bitmap>();
            frames.Add(TripLOAMobile.Properties.Resources.Win_1b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_2b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_3b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_4b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_5b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_6b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_7b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_8b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_9b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_10b);
            frames.Add(TripLOAMobile.Properties.Resources.Win_11b);
            this.Size = new Size(frames[0].Width+2, frames[0].Height+2);
            this.actualAnimation = frames[0];
        }

        /// <summary>
        /// Starts the animation.
        /// </summary>
        public void StartAnimation()
        {
            if (USESTANDARDAPPLICATIONANIMATION)
            {
                if (!this.usingStandardApplicationAnimation)
                {
                    this.StopAnimation();//if already stopped, it doesn't do nothing
                    this.loadAndSetApplicationDefaultAnimation();
                }
            }
            else//have to utilize the mobile-like animation
                if (this.usingStandardApplicationAnimation)
                {
                    this.StopAnimation();
                    this.loadAndSetMobileDefaultAnimation();
                }
            
            //no need to change kind of animation
            if (!this.isAnimating)
            {
                this.isAnimating = true;
                this.Enabled = true;
                this.Visible = true;
                this.actualPosition = 0;

                fTimer.Enabled = true;//Start the timer
            }
        }

        /// <summary>
        /// Stops the animation.
        /// </summary>
        public void StopAnimation()
        {
            if (this.isAnimating)
            {
                this.isAnimating = false;
                this.Enabled = false;
                this.Visible = false;
                //Stop the timer
                fTimer.Enabled = false;
                this.Invalidate();
                this.Update();
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //base.OnPaintBackground(e);
        }

        /// <summary>
        /// Raises the <see cref="E:Paint"/> event.
        /// </summary>
        /// <param name="pe">The <see cref="System.Windows.Forms.PaintEventArgs"/> instance containing the event data.</param>
        protected override void OnPaint(PaintEventArgs pe)
        {
            Graphics g = pe.Graphics;

            g.FillRectangle(brushBackGround, pe.ClipRectangle);
            if (this.usingStandardApplicationAnimation)
                g.DrawImage(this.actualAnimation, 1, 1);
            else
                g.DrawImage(this.actualAnimation, 0, 0);

            base.OnPaint(pe);
        }

        /// <summary>
        /// Gets the next animation frame.
        /// </summary>
        /// <returns></returns>
        private int getNextAnimation()
        {
            actualPosition++;
            actualPosition = actualPosition % (this.frames.Count);
            return actualPosition;
        }

        /// <summary>
        /// Handles the Tick event of the timer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void timer_Tick(object sender, System.EventArgs e)
        {
            int pos = this.getNextAnimation();
            this.actualAnimation = this.frames[pos];
        }
    }
}
